package application.view;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Date;
import java.util.ResourceBundle;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.methods.CloseableHttpResponse;

import com.jfinal.ext.kit.DateKit;
import com.jfinal.kit.StrKit;

import application.common.model.Config;
import application.common.util.ShiroUtil;
import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class MainController implements Initializable {

	@FXML
	private ProgressBar progressBar;

	@FXML
	private Label progressLabel;

	String soft_real_path;
	String soft_back_path;
	String server_url;
	String soft_name;
	JSONArray jsonArray;

	public void initialize(URL location, ResourceBundle resources) {

		Config config = Config.dao.findFirst("select * from " + Config.TABLE_NAME);
		if (config == null) {
			message("无效升级配置！", true);
			return;
		}

		soft_real_path = config.getSoftPath();
		soft_back_path = config.getSoftBackPath();
		server_url = config.getSynURL();
		soft_name = config.getSoftMainName();

		if (StrKit.isBlank(soft_name) || StrKit.isBlank(soft_real_path) || StrKit.isBlank(soft_back_path)
				|| StrKit.isBlank(server_url)) {
			message("升级程序配置有误！", true);
			return;
		}

		String backPath = soft_back_path + "/"
				+ DateKit.toStr(new Date(System.currentTimeMillis()), "yyyy-MM-dd-HH-mm-ss");

		Service<Integer> service = new Service<Integer>() {
			@Override
			protected Task<Integer> createTask() {
				return new Task<Integer>() {
					@Override
					protected Integer call() {
						CloseableHttpResponse response = null;
						CloseableHttpClient httpClient = null;
						try {

							httpClient = HttpClientBuilder.create().build();
							HttpGet httpGet = new HttpGet(server_url + "/api/soft/getUpdates");

							// 配置信息
							RequestConfig requestConfig = RequestConfig.custom()
									// 设置连接超时时间(单位毫秒)
									.setConnectTimeout(5000)
									// 设置请求超时时间(单位毫秒)
									.setConnectionRequestTimeout(5000)
									// socket读写超时时间(单位毫秒)
									.setSocketTimeout(5000)
									// 设置是否允许重定向(默认为true)
									.setRedirectsEnabled(true).build();
							httpGet.setConfig(requestConfig);

							// 由客户端执行(发送)Get请求
							response = httpClient.execute(httpGet);

							if (response == null) {
								throw new Exception("無響應！");
							}
							if (response.getStatusLine() == null) {
								throw new Exception("無響應！");
							}
							if (response.getEntity() == null) {
								throw new Exception("無響應！");
							}
							String content = EntityUtils.toString(response.getEntity(), "UTF-8");
							System.out.println("content=" + content);
							JSONObject jsonObject = JSONObject.fromObject(content);
							if (jsonObject == null) {
								throw new Exception("無響應！");
							}

							if (!jsonObject.has("code")) {
								throw new Exception("数据有误！");
							}

							int code = jsonObject.getInt("code");
							if (code != 200) {
								throw new Exception(jsonObject.getString("message"));
							}
							if (!jsonObject.has("data")) {
								throw new Exception("数据有误！");
							}

							String data = jsonObject.getString("data");

							if (StrKit.isBlank(data)) {
								throw new Exception("数据有误！");
							}

							jsonArray = JSONArray.fromObject(data);
							if (jsonArray == null || jsonArray.size() <= 0) {
								throw new Exception("无升级文件！");
							}

							message("创建备份路径...", true);
							File file = new File(backPath);
							if (!file.exists()) {
								if (!file.mkdirs()) {
									throw new Exception("创建备份路径失败！");
								}
							}
							int i = 0;
							message("下载升级包" + i + "/" + jsonArray.size() + "...", true);

							String version = "0";
							for (Object obj : jsonArray) {
								JSONObject item = JSONObject.fromObject(obj);
								if (item != null) {
									i++;
									String id = item.getString("id");
									String fileName = item.getString("fileName");
									String targetPath = item.getString("targetPath");
									version = item.getString("version");
									File softFile = new File(soft_real_path + targetPath);
									if (softFile.exists()) {
										try {
											Files.move(Paths.get(soft_real_path + targetPath),
													Paths.get(backPath + "/" + fileName),
													StandardCopyOption.REPLACE_EXISTING);
										} catch (IOException e) {
											throw e;
										}
									}
									message("开始下载升级包" + i + "/" + jsonArray.size() + "...", true);
									down(id, soft_real_path + targetPath);
									message("完成下载升级包" + i + "/" + jsonArray.size() + "...", true);
								}
							}
							config.setVersion(version);
							config.update();
							doJar(soft_real_path + "/" + soft_name);
							if (ShiroUtil.getMainProcess() != null) {
								ShiroUtil.getMainProcess().stop();
							}
							System.exit(0);
						} catch (Exception e) {
							e.printStackTrace();
							rollBack(backPath, jsonArray);
						} finally {
							if (response != null)
								try {
									response.close();
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							if (httpClient != null)
								try {
									httpClient.close();
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
						}
						message("升级失败...", true);
						return null;
					};
				};
			}
		};
		progressBar.progressProperty().bind(service.progressProperty());
		service.start();
	}

	private void message(final String text, final boolean isOk) {
		Platform.runLater(new Runnable() {
			public void run() {
				progressLabel.setText(text);
			}
		});
	}

	private void down(String id, String path) throws Exception {// throws Exception
		int byteread = 0;
		URL url = null;
		InputStream inStream = null;
		FileOutputStream fs = null;
		URLConnection conn = null;
		try {
			url = new URL(server_url + "/api/soft/down?fileId=" + id);
			conn = url.openConnection();
			inStream = conn.getInputStream();
			fs = new FileOutputStream(path);
			int progressTotal = inStream.available();
			if (progressTotal > 0) {
				byte[] buffer = new byte[inStream.available()];
				while ((byteread = inStream.read(buffer)) != -1) {
					fs.write(buffer, 0, byteread);
				}
				fs.flush();
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (fs != null) {
				try {
					fs.close();
				} catch (IOException e) {
				}
			}
			if (inStream != null) {
				try {
					inStream.close();
				} catch (IOException e) {
				}
			}
		}

	}

	private void doJar(String runPath) {
		try {
			Runtime.getRuntime().exec("java -jar " + runPath);
		}catch (Exception e) {
		}
	}

	private void rollBack(String backPath, JSONArray array) {
		if (array != null) {
			for (Object obj : array) {
				JSONObject item = JSONObject.fromObject(obj);
				if (item != null) {
					String fileName = item.getString("fileName");
					String targetPath = item.getString("targetPath");
					File softFile = new File(backPath + "/" + fileName);
					if (softFile.exists()) {
						try {
							Files.move(Paths.get(backPath + "/" + fileName), Paths.get(soft_real_path + targetPath),
									StandardCopyOption.REPLACE_EXISTING);
						} catch (IOException e) {
						}
					}
				}
			}
		}
		doJar(soft_real_path + "/" + soft_name);
		if (ShiroUtil.getMainProcess() != null) {
			try {
				ShiroUtil.getMainProcess().stop();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.exit(0);
	}

//	public static boolean isAlive(String procName) {
//		String cmd = "tasklist /fi \"" + "imagename eq " + procName + "\"";
//		Runtime process = Runtime.getRuntime();
//		Process p = null;
//		BufferedReader br = null;
//		try {
//			p = process.exec(cmd);
//			br = new BufferedReader(
//					new InputStreamReader(new BufferedInputStream(p.getInputStream()), Charset.forName("GB2312")));
//			String line = null;
//			while ((line = br.readLine()) != null) {
//				System.out.println(line);
//				if (line.contains(procName)) {
//					return true;
//				}
//			}
//			return false;
//		} catch (IOException e) {
//			e.printStackTrace();
//			return false;
//		} finally {
//			if (br != null) {
//				try {
//					br.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//			}
//		}
//	}


	public static final int getProcessID() {
		RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
		return Integer.valueOf(runtimeMXBean.getName().split("@")[0]).intValue();
	}
	

	public static void main(String[] args) {
		System.out.println(getProcessID());
		try {
			Runtime.getRuntime().exec("taskkill /F /PID " + getProcessID());
			System.out.println(getProcessID());
			while (true) {
				try {
					Thread.sleep(10000);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

}
